package com.robusta.app.catalogue.persistence;

import com.robusta.app.catalogue.model.CatalogueEntryModel;
import com.robusta.app.catalogue.model.CatalogueModel;
import com.robusta.app.domain.data.Pageable;
import com.robusta.app.domain.data.Searchable;
import com.robusta.app.domain.data.Sortable;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;

import static com.google.common.base.Strings.isNullOrEmpty;
import static org.hibernate.criterion.Projections.rowCount;
import static org.hibernate.criterion.Restrictions.eq;
import static org.hibernate.criterion.Restrictions.like;

@Repository
public class CatalogueRepositoryJpaHibernate implements CatalogueRepository {
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public int countOfEntriesMatching(Searchable searchable) {
        CatalogueModel catalogue = entityManager.find(CatalogueModel.class, searchable.catalogueId());
        Session session = (Session) entityManager.getDelegate();
        Criteria criteria = session
                .createCriteria(CatalogueEntryModel.class)
                .setProjection(rowCount())
                .add(eq("catalogue", catalogue));
        if(!isNullOrEmpty(searchable.textToMatch())) {
            criteria.add(like("description", makeSearchable(searchable.textToMatch())).ignoreCase());
        }
        return ((Long) criteria.uniqueResult()).intValue();
    }

    @Override
    public List<CatalogueEntryModel> searchForEntries(Searchable searchable, Pageable pageable, Sortable sortable) {
        CatalogueModel catalogue = entityManager.find(CatalogueModel.class, searchable.catalogueId());
        Session session = (Session) entityManager.getDelegate();
        Criteria criteria = session
                .createCriteria(CatalogueEntryModel.class)
                .add(eq("catalogue", catalogue));
        if(!isNullOrEmpty(searchable.textToMatch())) {
            criteria.add(like("description", makeSearchable(searchable.textToMatch())).ignoreCase());
        }
        criteria.setFirstResult((pageable.pageIndex() - 1) * pageable.rowsPerPage());
        criteria.setMaxResults(pageable.rowsPerPage());
        return criteria.list();
    }

    private String makeSearchable(String text) {
        return "%" + text.toLowerCase() + "%";
    }
}
